package com.stary.controller;


import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.stary.code.AutoGenerator;
import com.stary.code.springboot.config.LogBackConfig;
import com.stary.code.springboot.config.MailConfig;
import com.stary.code.springboot.config.MavenConfig;
import com.stary.code.springboot.config.MybatisPlusConfig;
import com.stary.code.springboot.config.SpringBootProjectConfig;
import com.stary.code.springboot.config.data.DataSourceConfig;
import com.stary.code.springboot.config.data.MongoDBConfig;
import com.stary.code.springboot.config.data.RedisConfig;
import com.stary.code.springboot.config.mq.ActiveMQConfig;
import com.stary.code.springboot.config.mq.KafkaConfig;
import com.stary.code.springboot.config.mq.RabbitMQConfig;
import com.stary.code.springboot.config.search.ElasticSearchConfig;
import com.stary.code.springboot.config.search.SolrConfig;
import com.stary.code.springboot.rules.SimpleDependency;
import com.stary.code.util.JDBCUtils;
import com.stary.code.util.ZipUtils;
import com.stary.mybatisplus.generator.config.DbDriverName;
import com.stary.service.GenerateService;

/**
 * @author stary
 * @date 2018年7月22日 上午10:04:02
 */
@Controller
public class IndexController {

	private static final Logger logger =LoggerFactory.getLogger(IndexController.class);

	private ExecutorService executorService;
	private Future<String> future;
	/**
	 * 首页 index
	 * @return
	 */
	@GetMapping("/index")
	public String index(String lang){

		if(!StringUtils.isEmpty(lang)){
			return "index_"+lang;			
		}else{
			return "index_cn";
		}

	}
	/**
	 * 生成项目请求
	 */
	@PostMapping(value="/generate")
	public void create(HttpServletRequest request,HttpServletResponse response,AutoGenerator generator,
			String artifactId,String groupId,String packaging,String name ,String description,
			boolean openDataSource,boolean openView,boolean openLogback,String viewType,boolean tableDocCreated,
			String logfilePath,String logfileName,Integer logmaxHistory,String logmaxFileSize,String logoutFormat,
			String springBootVersion,String javaVersion,String[] dependency,
			String type,String url,String poolType,String username,String password,
			String table,String tablePrefix,
			int rdatabase,String rhost,int rport,String rpassword,
			String mhost,int mport,String mdatabase,String musername,String mpassword,
			String mailhost,String mailusername,String mailpassword,
			String activeurl,String activeuser,String activepassword,boolean activepoolEnabled,boolean activeinMemory,
			String rabbithost,int rabbitport,String virtualHost,String rabbitusername,String rabbitpassword,
			String bootstrapServers,String consumerGroupId,String consumerAutoOffsetReset,boolean consumerEnableAutoCommit,
			String solrhost,String solrzkHost,
			String esclusterName,String esclusterNodes) throws IOException, InterruptedException, ExecutionException{
		// 线程池
		executorService=Executors.newFixedThreadPool(3);
		// 生成绝对路径
		String outDir=request.getSession().getServletContext().getRealPath("/generate_code")+"/";
		generator.setOutDir(outDir);
		// mavenConfig
		MavenConfig mavenConfig=setMavenConfig(
				artifactId, groupId, packaging, name, description);	
		// springBootProjectConfig
		SpringBootProjectConfig springBootProjectConfig=setSpringBootProjectConfig(
				openDataSource, openView, openLogback,tableDocCreated,viewType, springBootVersion, javaVersion, dependency);
		// dataSourceConfig
		DataSourceConfig dataSourceConfig=setDataSourceConfig(type, url, poolType, username, password);
		// mybatisPlusConfig
		MybatisPlusConfig mybatisPlusConfig=setMybatisPlusConfig(table, tablePrefix);
		// logBackConfig
		LogBackConfig logBackConfig=setLogBackConfig(logfilePath, logfileName, logmaxHistory, logmaxFileSize, logoutFormat);
		// redisConfig
		RedisConfig redisConfig=setRedisConfig(rdatabase, rhost, rport, rpassword);
		// mongoDBConfig
		MongoDBConfig mongoDBConfig=setMongoDBConfig(mhost, mport, mdatabase, musername, mpassword);
		// mailConfig
		MailConfig mailConfig=setMailConfig(mailhost, mailusername, mailpassword);
		// activeMQConfig
		ActiveMQConfig activeMQConfig=setActiveMQConfig(activeurl, activeuser, activepassword, activepoolEnabled, activeinMemory);
		// rabbitMQConfig
		RabbitMQConfig rabbitMQConfig=setRabbitMQConfig(rabbithost, rabbitport, virtualHost, rabbitusername, rabbitpassword);
		// kafkaConfig
		KafkaConfig kafkaConfig=setKafkaConfig(bootstrapServers, consumerGroupId, consumerEnableAutoCommit, consumerAutoOffsetReset);
		// solrConfig
		SolrConfig solrConfig=setSolrConfig(solrhost, solrzkHost);
		// elasticSearchConfig
		ElasticSearchConfig elasticSearchConfig=setElasticSearchConfig(esclusterName, esclusterNodes);
		
		// submit task
		if(executorService!=null && !executorService.isShutdown()){

			future=executorService.submit(
					new GenerateService(
							generator, mavenConfig, springBootProjectConfig, logBackConfig, 
							mybatisPlusConfig, dataSourceConfig, redisConfig, mongoDBConfig, 
							mailConfig, activeMQConfig, rabbitMQConfig, kafkaConfig,
							solrConfig,elasticSearchConfig));
			executorService.shutdown();			
		}
		if(future !=null){
			String result=future.get();
			if("1".equals(result)){
				response.setHeader("Content-disposition", "attachment;filename=" + mavenConfig.getArtifactId()+".zip");
				ZipUtils.toZip(outDir+"/"+mavenConfig.getArtifactId(), response.getOutputStream(), true);
			}
			Thread.sleep(1000);
			delFolder(outDir+"/"+mavenConfig.getArtifactId());
		}

	}
	/**
	 * maven工程配置
	 * @param artifactId
	 * @param groupId
	 * @param packaging
	 * @param name
	 * @param description
	 * @return
	 */
	public MavenConfig setMavenConfig(
			String artifactId,String groupId,String packaging,String name ,String description){
		MavenConfig config=new MavenConfig();
		config.setArtifactId(artifactId);
		config.setGroupId(groupId);
		config.setPackaging(packaging);
		if(!StringUtils.isEmpty(name)){
			config.setName(name);			
		}
		if(!StringUtils.isEmpty(description)){		
			config.setDescription(description);
		}
		return config;
	}
	
	
	public LogBackConfig setLogBackConfig(String logfilePath,String logfileName,Integer logmaxHistory,String logmaxFileSize,String logoutFormat){
		LogBackConfig config=new LogBackConfig();
		if(!StringUtils.isEmpty(logfileName)){
			config.setFileName(logfileName);		
		}
		if(!StringUtils.isEmpty(logfilePath)){
			config.setFilePath(logfilePath);	
		}
		if(!StringUtils.isEmpty(logoutFormat)){
			config.setOutFormat(logoutFormat);		
		}
		if(!StringUtils.isEmpty(logmaxFileSize)){
			config.setMaxFileSize(logmaxFileSize);		
		}
		if(logmaxHistory!=null){
			config.setMaxHistory(logmaxHistory);		
		}
		
		return config;
	}
	
	public SpringBootProjectConfig setSpringBootProjectConfig(
			Boolean openDataSource,Boolean openView,Boolean openLogback,Boolean tableDocCreated,String viewType, 
			String springBootVersion,String javaVersion,String[] dependency){
		SpringBootProjectConfig config=new SpringBootProjectConfig();
		config.setSpringBootVersion(springBootVersion);
		config.setJavaVersion(javaVersion);
		config.setOpenDataSource(openDataSource);			
		config.setOpenView(openView);	
		config.setOpenLogback(openLogback);
		config.setTableDocCreated(tableDocCreated);
		config.setViewType(viewType);
		if(!StringUtils.isEmpty(dependency)){
			Map<String, String> map=new HashMap<>();
			for (int i = 0; i < dependency.length; i++) {
				if(SimpleDependency.MYBATIS_PLUS.getName().equals(dependency[i])){
					map.put(SimpleDependency.MYBATIS_PLUS.getName(), SimpleDependency.MYBATIS_PLUS.getCode());					
				}
				if(SimpleDependency.REDIS.getName().equals(dependency[i])){
					map.put(SimpleDependency.REDIS.getName(), SimpleDependency.REDIS.getCode());					
				}
				if(SimpleDependency.MONGODB.getName().equals(dependency[i])){
					map.put(SimpleDependency.MONGODB.getName(), SimpleDependency.MONGODB.getCode());					
				}
				if(SimpleDependency.MAIL.getName().equals(dependency[i])){
					map.put(SimpleDependency.MAIL.getName(), SimpleDependency.MAIL.getCode());					
				}
				if(SimpleDependency.SHIRO.getName().equals(dependency[i])){
					map.put(SimpleDependency.SHIRO.getName(), SimpleDependency.SHIRO.getCode());					
				}
				if(SimpleDependency.SCHEDULE.getName().equals(dependency[i])){
					map.put(SimpleDependency.SCHEDULE.getName(), SimpleDependency.SCHEDULE.getCode());					
				}
				if(SimpleDependency.QUARTZ.getName().equals(dependency[i])){
					map.put(SimpleDependency.QUARTZ.getName(), SimpleDependency.QUARTZ.getCode());					
				}
				if(SimpleDependency.ACTIVEMQ.getName().equals(dependency[i])){
					map.put(SimpleDependency.ACTIVEMQ.getName(), SimpleDependency.ACTIVEMQ.getCode());					
				}
				if(SimpleDependency.RABBITMQ.getName().equals(dependency[i])){
					map.put(SimpleDependency.RABBITMQ.getName(), SimpleDependency.RABBITMQ.getCode());					
				}
				if(SimpleDependency.KAFKA.getName().equals(dependency[i])){
					map.put(SimpleDependency.KAFKA.getName(), SimpleDependency.KAFKA.getCode());					
				}
				if(SimpleDependency.JDBC.getName().equals(dependency[i])){
					map.put(SimpleDependency.JDBC.getName(), SimpleDependency.JDBC.getCode());					
				}
				if(SimpleDependency.SOLR.getName().equals(dependency[i])){
					map.put(SimpleDependency.SOLR.getName(), SimpleDependency.SOLR.getCode());					
				}
				if(SimpleDependency.ELASTICSEARCH.getName().equals(dependency[i])){
					map.put(SimpleDependency.ELASTICSEARCH.getName(), SimpleDependency.ELASTICSEARCH.getCode());					
				}
			}
			config.setDependencyMap(map);
		}
		return config;
	}
	/**
	 * 数据源配置
	 * @param type
	 * @param url
	 * @param poolType
	 * @param username
	 * @param password
	 * @return
	 */
	public DataSourceConfig setDataSourceConfig(
			String type,String url,String poolType,String username,String password){
		DataSourceConfig config=new DataSourceConfig();
		config.setType(type);
		config.setPoolType(poolType);
		config.setUrl(url);
		config.setPassword(password);
		config.setUsername(username);
		return config;
	}
	/**
	 * MybatisPlus配置
	 * @param table
	 * @param tablePrefix
	 * @return
	 */
	public MybatisPlusConfig setMybatisPlusConfig(String table,String tablePrefix){
		MybatisPlusConfig config=new MybatisPlusConfig();
		if (!StringUtils.isEmpty(table)) {
			String[] tables=table.split(",");
			config.setTables(tables);
		}
		if (!StringUtils.isEmpty(tablePrefix)) {
			String[] tablePrefixs=tablePrefix.split(",");
			config.setTablePrefixs(tablePrefixs);
		}
		return config;

	}
	/**
	 * Redis配置
	 * @param database
	 * @param host
	 * @param port
	 * @param password
	 * @return
	 */
	public RedisConfig setRedisConfig(int database,String host,int port,String password){
		RedisConfig config=new RedisConfig();
		config.setDatabase(database);
		config.setHost(host);
		config.setPassword(password);
		config.setPort(port);
		return config;
	}
	/**
	 * mongoDB配置
	 * @param host
	 * @param port
	 * @param database
	 * @param username
	 * @param password
	 * @return
	 */
	public MongoDBConfig setMongoDBConfig(String host,int port,String database,String username,String password){
		MongoDBConfig config=new MongoDBConfig();
		config.setHost(host);
		config.setPort(port);
		config.setDatabase(database);
		config.setUsername(username);
		config.setPassword(password);
		return config;

	}
	/**
	 * mail配置
	 * @param host
	 * @param username
	 * @param password
	 * @return
	 */
	public MailConfig setMailConfig(String host,String username,String password){
		MailConfig mailConfig=new MailConfig();
		mailConfig.setHost(host);
		mailConfig.setPassword(password);
		mailConfig.setUsername(username);
		return mailConfig;
	}
	/**
	 * activeMQ配置
	 * @param url
	 * @param user
	 * @param password
	 * @param poolEnabled
	 * @param inMemory
	 * @return
	 */
	public ActiveMQConfig setActiveMQConfig(String url,String user,String password,boolean poolEnabled,boolean inMemory){
		ActiveMQConfig activeMQConfig=new ActiveMQConfig();
		activeMQConfig.setUrl(url);
		activeMQConfig.setUser(user);
		activeMQConfig.setPassword(password);
		activeMQConfig.setPoolEnabled(poolEnabled);
		activeMQConfig.setInMemory(inMemory);
		return activeMQConfig;
	}
	/**
	 * rabbitMQ配置
	 * @param host
	 * @param port
	 * @param virtualHost
	 * @param username
	 * @param password
	 * @return
	 */
	public RabbitMQConfig setRabbitMQConfig(String host,int port,String virtualHost,String username,String password){
		RabbitMQConfig rabbitMQConfig=new RabbitMQConfig();
		rabbitMQConfig.setHost(host);
		rabbitMQConfig.setPort(port);
		rabbitMQConfig.setVirtualHost(virtualHost);
		rabbitMQConfig.setUsername(username);
		rabbitMQConfig.setPassword(password);
		return rabbitMQConfig;
	}
	/**
	 * kafka配置
	 * @param bootstrapServers
	 * @param consumerGroupId
	 * @param consumerEnableAutoCommit
	 * @param consumerAutoOffsetReset
	 * @return
	 */
	public KafkaConfig setKafkaConfig(String bootstrapServers,String consumerGroupId,boolean consumerEnableAutoCommit,String consumerAutoOffsetReset){
		KafkaConfig kafkaConfig=new KafkaConfig();
		kafkaConfig.setBootstrapServers(bootstrapServers);
		kafkaConfig.setConsumerGroupId(consumerGroupId);
		kafkaConfig.setConsumerEnableAutoCommit(consumerEnableAutoCommit);
		kafkaConfig.setConsumerAutoOffsetReset(consumerAutoOffsetReset);
		return kafkaConfig;
	}
	/**
	 * solr配置
	 * @param host
	 * @param zkHost
	 * @return
	 */
	public SolrConfig setSolrConfig(String host,String zkHost){
		SolrConfig config=new SolrConfig();
		config.setHost(host);
		config.setZkHost(zkHost);
		return config;
	}
	/**
	 * elasticsearch配置
	 * @param clusterName
	 * @param clusterNodes
	 * @return
	 */
	public ElasticSearchConfig setElasticSearchConfig(String clusterName,String clusterNodes){
		ElasticSearchConfig config=new ElasticSearchConfig();
		config.setClusterName(clusterName);
		config.setClusterNodes(clusterNodes);
		return config;
	}
	/**
	 * 删除文件夹
	 * @param folderPath
	 */
	private static void delFolder(String folderPath) {  
		try {  
			delAllFile(folderPath); //删除完里面所有内容  
			String filePath = folderPath;  
			filePath = filePath.toString();  
			File myFilePath = new File(filePath);  
			myFilePath.delete(); //删除空文件夹  
		} catch (Exception e) {  
			e.printStackTrace();   
		}  
	}  

	/**
	 * 删除所有文件
	 * @param path
	 * @return
	 */
	private static boolean delAllFile(String path) {  
		boolean flag = false;  
		File file = new File(path);  
		if (!file.exists()) {  
			return flag;  
		}  
		if (!file.isDirectory()) {  
			return flag;  
		}  
		String[] tempList = file.list();  
		File temp = null;  
		for (int i = 0; i < tempList.length; i++) {  
			if (path.endsWith(File.separator)) {  
				temp = new File(path + tempList[i]);  
			} else {  
				temp = new File(path + File.separator + tempList[i]);  
			}  
			if (temp.isFile()) {  
				temp.delete();  
			}  
			if (temp.isDirectory()) {  
				delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件  
				delFolder(path + "/" + tempList[i]);//再删除空文件夹  
				flag = true;  
			}  
		}  
		return flag;  
	}
	/**
	 * 获取数据库下的表名信息
	 * @param type
	 * @param url
	 * @param username
	 * @param password
	 * @return
	 */
	@PostMapping("/get_table_names.do")
	@ResponseBody
	public List<String> getTableName(String type,String url,String username,String password){
		List<String> list=null;
		String driverClassName=null;
		if(DbDriverName.ORACLE.getDb().equals(type)){
			driverClassName=DbDriverName.ORACLE.getName();
		}else if(DbDriverName.MYSQL.getDb().equals(type)){
			driverClassName=DbDriverName.MYSQL.getName();
		}else if(DbDriverName.SQLSERVER.getDb().equals(type)){
			driverClassName=DbDriverName.SQLSERVER.getName();
		}
		try {
			list=JDBCUtils.getTableNames(driverClassName, url, username, password);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error("获取数据库下的表信息出现异常:{}",e.getMessage());
		}
		return list;

	}
}
